from dataclasses import dataclass

from fastapi import status
from fastapi.exceptions import HTTPException

from app.controllers.base_controller import BaseController
from app.models.region_models import Region
from app.schemas.region_schemas import (CreateRegionRequestSchema,
                                        CreateRegionResponseSchema,
                                        GetRegionResponseSchema,
                                        RegionEditRequestSchema,
                                        RegionEditResponseSchema)
from app.tools.region_tools import RegionTools


@dataclass
class CreateRegionController(BaseController):
    """Контроллер создания региона"""

    account_id: int
    request: CreateRegionRequestSchema

    async def execute(self) -> CreateRegionResponseSchema:
        region_type = await RegionTools.validate_region_request(request=self.request)

        new_region = await Region.create(
            regionType=region_type,
            accountId=self.account_id,
            name=self.request.name,
            parentRegion=self.request.parentRegion,
            latitude=self.request.latitude,
            longitude=self.request.longitude,
            latitude1=self.request.latitude1,
            longitude1=self.request.longitude1
        )

        return CreateRegionResponseSchema(
            id=new_region.id,
            name=new_region.name,
            parentRegion=new_region.parentRegion,
            regionType=new_region.regionType_id,
            latitude=new_region.latitude,
            longitude=new_region.longitude,
            latitude1=self.request.latitude1,
            longitude1=self.request.longitude1
        )


@dataclass
class GetRegionByIdController(BaseController):
    """Контроллер получения региона по ID"""

    region_id: int

    async def execute(self) -> GetRegionResponseSchema:
        if self.region_id is None or self.region_id <= 0:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)

        region = await Region.get_or_none(id=self.region_id)

        if region is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

        if region.regionType:
            region_type = region.regionType_id
        else:
            region_type = None

        return GetRegionResponseSchema(
            id=region.id,
            regionType=region_type,
            accountId=region.accountId,
            name=region.name,
            parentRegion=region.parentRegion,
            latitude=region.latitude,
            longitude=region.longitude,
            latitude1=region.latitude1,
            longitude1=region.longitude1
        )


@dataclass
class EditRegionController(BaseController):
    """Контроллер редактирования региона"""

    region_id: int
    request: RegionEditRequestSchema

    async def execute(self) -> RegionEditResponseSchema:
        region_type = await RegionTools.validate_region_request(request=self.request)

        region = await Region.get_or_none(id=self.region_id)

        if region is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

        region.name = self.request.name
        region.parentRegion = self.request.parentRegion
        region.regionType = region_type
        region.latitude = self.request.latitude
        region.longitude = self.request.longitude
        region.latitude1 = self.request.latitude1
        region.longitude1 = self.request.longitude1

        await region.save()

        return RegionEditResponseSchema(
            id=region.id,
            name=region.name,
            parentRegion=region.parentRegion,
            latitude=region.latitude,
            longitude=region.longitude,
            latitude1=region.latitude1,
            longitude1=region.longitude1
        )


@dataclass
class DeleteRegionController(BaseController):
    """Контроллер удаления региона"""

    region_id: int

    async def execute(self) -> None:
        if self.region_id is None or self.region_id <= 0:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)

        region = await Region.get_or_none(id=self.region_id)

        if region is None:
            raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)

        child_region = await Region.filter(parentRegion=region.name)

        if len(child_region) > 0:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST)

        await region.delete()
